#include "includes.h"
#include "vo_impl.h"

#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))

#define GET_LAYER_FROM_VODEV(VoDev) (VoDev)

MPP_VO_VIDEO_LAYER_S g_stVideoLayers[VO_VIDEO_LAYER_MAX_NUM];
MPP_VO_DEVICE_S g_stVoDevices[VO_DEV_MAX_NUM];

MPP_VO_CONTEXT_S g_VoCtx;

static void *vo_device_proc_thread(void *arg);

int32_t TR_VO_Module_Init()
{
    int i;

    memset(g_stVoDevices, 0L, sizeof(g_stVoDevices));

    //init vo ctx
    memset(&g_VoCtx, 0L, sizeof(MPP_VO_CONTEXT_S));
    g_VoCtx.quit = 0;
    g_VoCtx.threadId = -1;
    pthread_mutex_init(&g_VoCtx.stMutex, NULL);
    g_VoCtx.s32Ref = 1;

    memset(g_stVideoLayers, 0L, sizeof(g_stVideoLayers));

    for (i = 0; i < ARRAY_SIZE(g_stVideoLayers); i++)
    {
        g_stVideoLayers[i].bEnable = FALSE;
        g_stVideoLayers[i].voLayerId = i;
    }

    return TR_SUCCESS;
}

int32_t TR_VO_Module_DeInit()
{
    //deinit vo ctx
    g_VoCtx.s32Ref = 0;
    g_VoCtx.threadId = -1;
    pthread_mutex_destroy(&g_VoCtx.stMutex);

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_SetPubAttr(VO_DEV VoDev, const VO_PUB_ATTR_S *pstPubAttr)
{
    MPP_VO_DEVICE_S *pstVoDev;

    assert(VoDev >= 0 && VoDev < VO_DEV_MAX_NUM);

    pstVoDev = &g_stVoDevices[VoDev];
    memcpy(&pstVoDev->stAttr, pstPubAttr, sizeof(VO_PUB_ATTR_S));

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_GetPubAttr(VO_DEV VoDev, VO_PUB_ATTR_S *pstPubAttr)
{
    MPP_VO_DEVICE_S *pstVoDev;

    assert(VoDev >= 0 && VoDev < VO_DEV_MAX_NUM);

    pstVoDev = &g_stVoDevices[VoDev];
    memcpy(pstPubAttr, &pstVoDev->stAttr, sizeof(VO_PUB_ATTR_S));

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_Enable (VO_DEV VoDev)
{
    MPP_VO_DEVICE_S *pstVoDev;

    assert(VoDev >= 0 && VoDev < VO_DEV_MAX_NUM);

    pstVoDev = &g_stVoDevices[VoDev];
    pstVoDev->bEnable = TRUE;

    memset(pstVoDev->pLayers, 0L, sizeof(pstVoDev->pLayers));

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_Disable(VO_DEV VoDev)
{
    MPP_VO_DEVICE_S *pstVoDev;

    assert(VoDev >= 0 && VoDev < VO_DEV_MAX_NUM);

    pstVoDev = &g_stVoDevices[VoDev];
    pstVoDev->bEnable = FALSE;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_CloseFd(HI_VOID)
{
    return HI_SUCCESS;
}

HI_S32 TR_MPI_VO_SetVideoLayerSurface(VO_LAYER VoLayer, const void *pSurface)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];
    pstLayer->pSurface = (ANativeWindow *)pSurface;

    return TR_SUCCESS;
}

HI_S32 TR_MPI_VO_GetVideoLayerSurface(VO_LAYER VoLayer, void **pSurface)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];
    *pSurface = pstLayer->pSurface;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_SetVideoLayerAttr(VO_LAYER VoLayer, const VO_VIDEO_LAYER_ATTR_S *pstLayerAttr)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];
    pstLayer->stDispRect = pstLayerAttr->stDispRect;
    pstLayer->stImageSize = pstLayerAttr->stImageSize;
    pstLayer->u32FrameRate = pstLayerAttr->u32FrameRate;
    pstLayer->enPixelFormat = pstLayerAttr->enPixelFormat;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_GetVideoLayerAttr(VO_LAYER VoLayer, VO_VIDEO_LAYER_ATTR_S *pstLayerAttr)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];
    pstLayerAttr->stDispRect = pstLayer->stDispRect;
    pstLayerAttr->stImageSize = pstLayer->stImageSize;
    pstLayerAttr->u32FrameRate = pstLayer->u32FrameRate;
    pstLayerAttr->enPixelFormat = pstLayer->enPixelFormat;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_SetVideoLayerCompressAttr(VO_LAYER VoLayer, const VO_COMPRESS_ATTR_S *pstCompressAttr)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetVideoLayerCompressAttr(VO_LAYER VoLayer, VO_COMPRESS_ATTR_S *pstCompressAttr)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_EnableVideoLayer (VO_LAYER VoLayer)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;
    MPP_VO_CONTEXT_S *pCtx;

    pCtx = &g_VoCtx;
    pstLayer = &g_stVideoLayers[VoLayer];

    pthread_mutex_lock(&pCtx->stMutex);

    pstLayer->s32MaxChnNum = VO_MAX_CHN_NUM;
    pstLayer->pstChannels = (MPP_VO_CHANNEL_S *)calloc(pstLayer->s32MaxChnNum, sizeof(MPP_VO_CHANNEL_S));
    pstLayer->bEnable = TRUE;
    //pstLayer->pReversePtr = vo ptr;

    TR_MPI_SYS_PIN_DATA_Init_I(&pstLayer->stPinData, VO_MAX_CHN_NUM, 1);

    //if has vo enable ,create vo_thread
    if (pCtx->s32Ref == 0)
    {
        pthread_create(&pCtx->threadId, NULL, vo_device_proc_thread, NULL);
    }

    pCtx->s32Ref++;

    pthread_mutex_unlock(&pCtx->stMutex);

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_DisableVideoLayer(VO_LAYER VoLayer)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;
    MPP_VO_CONTEXT_S *pCtx;

    pCtx = &g_VoCtx;
    pstLayer = &g_stVideoLayers[VoLayer];

    pthread_mutex_lock(&pCtx->stMutex);

    TR_MPI_SYS_PIN_DATA_DeInit_I(&pstLayer->stPinData);

    pstLayer->bEnable = FALSE;
    pstLayer->s32MaxChnNum = 0;
    if (pstLayer->pstChannels)
    {
        free(pstLayer->pstChannels);
        pstLayer->pstChannels = NULL;
    }

    if (pCtx->s32Ref == 0 && pCtx->threadId > 0)
    {
        pthread_join(pCtx->threadId, NULL);
        pCtx->threadId = -1;
    }

    if (pCtx->s32Ref > 0)
        pCtx->s32Ref--;
    
    pthread_mutex_unlock(&pCtx->stMutex);

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_BindVideoLayer(VO_LAYER VoLayer, VO_DEV VoDev)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_UnBindVideoLayer(VO_LAYER VoLayer, VO_DEV VoDev)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetVideoLayerPriority(VO_LAYER VoLayer, HI_U32 u32Priority)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetVideoLayerPriority(VO_LAYER VoLayer, HI_U32 *pu32Priority)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetVideoLayerCSC(VO_LAYER VoLayer, const VO_CSC_S *pstVideoCSC)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetVideoLayerCSC(VO_LAYER VoLayer, VO_CSC_S *pstVideoCSC)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetVideoLayerPartitionMode(VO_LAYER VoLayer, VO_PART_MODE_E enPartMode)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetVideoLayerPartitionMode(VO_LAYER VoLayer, VO_PART_MODE_E *penPartMode)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetAttrBegin(VO_LAYER VoLayer)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetAttrEnd  (VO_LAYER VoLayer)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetScreenFrame(VO_LAYER VoLayer, VIDEO_FRAME_INFO_S *pstVFrame, HI_S32 s32MilliSec)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_ReleaseScreenFrame(VO_LAYER VoLayer, VIDEO_FRAME_INFO_S *pstVFrame)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetDispBufLen(VO_LAYER VoLayer, HI_U32 u32BufLen)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetDispBufLen(VO_LAYER VoLayer, HI_U32 *pu32BufLen)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_EnableChn (VO_LAYER VoLayer, VO_CHN VoChn)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];

    if (!pstLayer->bEnable)
    {
        return TR_FAILURE;
    }

    pstLayer->pstChannels[VoChn].bEnable = TRUE;
    pstLayer->pstChannels[VoChn].bVisable = TRUE;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_DisableChn(VO_LAYER VoLayer, VO_CHN VoChn)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];

    if (!pstLayer->bEnable)
    {
        return TR_FAILURE;
    }

    pstLayer->pstChannels[VoChn].bEnable = FALSE;
    pstLayer->pstChannels[VoChn].bVisable = FALSE;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_SetChnAttr(VO_LAYER VoLayer, VO_CHN VoChn, const VO_CHN_ATTR_S *pstChnAttr)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];

    if (!pstLayer->bEnable)
    {
        return TR_FAILURE;
    }

    pstLayer->pstChannels[VoChn].u32FrameRate = pstChnAttr->u32FrameRate;
    pstLayer->pstChannels[VoChn].u32Priority = pstChnAttr->u32Priority;
    pstLayer->pstChannels[VoChn].stRect = pstChnAttr->stRect;
    pstLayer->pstChannels[VoChn].bDeflicker = pstChnAttr->bDeflicker;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_GetChnAttr(VO_LAYER VoLayer, VO_CHN VoChn, VO_CHN_ATTR_S *pstChnAttr)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];

    if (!pstLayer->bEnable)
    {
        return TR_FAILURE;
    }

    pstChnAttr->u32FrameRate = pstLayer->pstChannels[VoChn].u32FrameRate;
    pstChnAttr->u32Priority = pstLayer->pstChannels[VoChn].u32Priority;
    pstChnAttr->stRect = pstLayer->pstChannels[VoChn].stRect;
    pstChnAttr->bDeflicker = pstLayer->pstChannels[VoChn].bDeflicker;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_SetChnParam(VO_LAYER VoLayer, VO_CHN VoChn, const VO_CHN_PARAM_S *pstChnParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetChnParam(VO_LAYER VoLayer, VO_CHN VoChn, VO_CHN_PARAM_S *pstChnParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetChnDispPos(VO_LAYER VoLayer, VO_CHN VoChn, const POINT_S *pstDispPos)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];

    if (!pstLayer->bEnable)
    {
        return TR_FAILURE;
    }

    pstLayer->pstChannels[VoChn].stRect.s32X = pstDispPos->s32X;
    pstLayer->pstChannels[VoChn].stRect.s32Y = pstDispPos->s32Y;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_GetChnDispPos(VO_LAYER VoLayer, VO_CHN VoChn, POINT_S *pstDispPos)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];

    if (!pstLayer->bEnable)
    {
        return TR_FAILURE;
    }

    pstDispPos->s32X = pstLayer->pstChannels[VoChn].stRect.s32X;
    pstDispPos->s32Y = pstLayer->pstChannels[VoChn].stRect.s32Y;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_SetChnField(VO_LAYER VoLayer, VO_CHN VoChn, const VO_DISPLAY_FIELD_E enField)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetChnField(VO_LAYER VoLayer, VO_CHN VoChn, VO_DISPLAY_FIELD_E *pField)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetChnFrameRate(VO_LAYER VoLayer, VO_CHN VoChn, HI_S32 s32ChnFrmRate)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];

    if (!pstLayer->bEnable)
    {
        return TR_FAILURE;
    }

    pstLayer->pstChannels[VoChn].u32FrameRate = s32ChnFrmRate;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_GetChnFrameRate(VO_LAYER VoLayer, VO_CHN VoChn, HI_S32 *ps32ChnFrmRate)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];

    if (!pstLayer->bEnable)
    {
        return TR_FAILURE;
    }

    *ps32ChnFrmRate = pstLayer->pstChannels[VoChn].u32FrameRate;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_GetChnFrame(VO_LAYER VoLayer, VO_CHN VoChn, VIDEO_FRAME_INFO_S *pstFrame, HI_S32 s32MilliSec)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_ReleaseChnFrame(VO_LAYER VoLayer, VO_CHN VoChn, const VIDEO_FRAME_INFO_S *pstFrame)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_PauseChn (VO_LAYER VoLayer, VO_CHN VoChn)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_ResumeChn(VO_LAYER VoLayer, VO_CHN VoChn)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_StepChn(VO_LAYER VoLayer, VO_CHN VoChn)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_RefreshChn( VO_LAYER VoLayer, VO_CHN VoChn)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_ShowChn(VO_LAYER VoLayer, VO_CHN VoChn)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];

    if (!pstLayer->bEnable)
    {
        return TR_FAILURE;
    }

    pstLayer->pstChannels[VoChn].bVisable = TRUE;

    //触发重新绘制

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_HideChn(VO_LAYER VoLayer, VO_CHN VoChn)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];

    if (!pstLayer->bEnable)
    {
        return TR_FAILURE;
    }

    pstLayer->pstChannels[VoChn].bVisable = FALSE;

    return TR_SUCCESS;
}

HI_S32 HI_MPI_VO_SetZoomInWindow(VO_LAYER VoLayer, VO_CHN VoChn, const VO_ZOOM_ATTR_S *pstZoomAttr)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetZoomInWindow(VO_LAYER VoLayer, VO_CHN VoChn, VO_ZOOM_ATTR_S *pstZoomAttr)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetPlayToleration(VO_LAYER VoLayer, HI_U32 u32Toleration)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetPlayToleration(VO_LAYER VoLayer, HI_U32 *pu32Toleration)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetChnPts   (VO_LAYER VoLayer, VO_CHN VoChn, HI_U64 *pu64ChnPts)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_QueryChnStat(VO_LAYER VoLayer, VO_CHN VoChn, VO_QUERY_STATUS_S *pstStatus)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SendFrame(VO_LAYER VoLayer, VO_CHN VoChn, VIDEO_FRAME_INFO_S *pstVFrame, HI_S32 s32MilliSec)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_ClearChnBuffer(VO_LAYER VoLayer, VO_CHN VoChn, HI_BOOL bClrAll)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetChnBorder(VO_LAYER VoLayer, VO_CHN VoChn, const VO_BORDER_S *pstBorder)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetChnBorder(VO_LAYER VoLayer, VO_CHN VoChn, VO_BORDER_S *pstBorder)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetChnReceiveThreshold(VO_LAYER VoLayer, VO_CHN VoChn, HI_U32 u32Threshold)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetChnReceiveThreshold(VO_LAYER VoLayer, VO_CHN VoChn, HI_U32 *pu32Threshold)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetWbcSource(VO_WBC VoWbc, const VO_WBC_SOURCE_S *pstWbcSource)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetWbcSource(VO_WBC VoWbc, VO_WBC_SOURCE_S *pstWbcSources)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_EnableWbc(VO_WBC VoWbc)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_DisableWbc(VO_WBC VoWbc)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetWbcAttr(VO_WBC VoWbc, const VO_WBC_ATTR_S *pstWbcAttr)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetWbcAttr(VO_WBC VoWbc, VO_WBC_ATTR_S *pstWbcAttr)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetWbcMode(VO_WBC VoWbc, VO_WBC_MODE_E enWbcMode)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetWbcMode(VO_WBC VoWbc, VO_WBC_MODE_E *penWbcMode)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetWbcDepth(VO_WBC VoWbc, HI_U32 u32Depth)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetWbcDepth(VO_WBC VoWbc, HI_U32 *pu32Depth)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetWbcFrame(VO_WBC VoWbc, VIDEO_FRAME_INFO_S *pstVFrame, HI_S32 s32MilliSec)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_ReleaseWbcFrame(VO_WBC VoWbc, VIDEO_FRAME_INFO_S *pstVFrame)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_BindGraphicLayer(GRAPHIC_LAYER GraphicLayer, VO_DEV VoDev)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_UnBindGraphicLayer(GRAPHIC_LAYER GraphicLayer, VO_DEV VoDev)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetGraphicLayerCSC(GRAPHIC_LAYER GraphicLayer, const VO_CSC_S *pstCSC)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetGraphicLayerCSC(GRAPHIC_LAYER GraphicLayer, VO_CSC_S *pstCSC)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetCascadeAttr(const VO_CAS_ATTR_S *pstCasAttr)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetCascadeAttr(VO_CAS_ATTR_S *pstCasAttr)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_EnableCascadeDev (VO_DEV VoCasDev)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_DisableCascadeDev(VO_DEV VoCasDev)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetCascadePattern(VO_DEV VoCasDev, HI_U32 u32Pattern)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetCascadePattern(VO_DEV VoCasDev, HI_U32 *pu32Pattern)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_CascadePosBindChn(HI_U32 u32Pos, VO_DEV VoCasDev, VO_CHN VoChn)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_CascadePosUnBindChn(HI_U32 u32Pos, VO_DEV VoCasDev, VO_CHN VoChn)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_EnableCascade (HI_VOID)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_DisableCascade(HI_VOID)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetVgaParam(VO_DEV VoDev, VO_VGA_PARAM_S *pstVgaParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetVgaParam(VO_DEV VoDev, VO_VGA_PARAM_S *pstVgaParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetDevFrameRate(VO_DEV VoDev, HI_U32 u32FrameRate)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetDevFrameRate(VO_DEV VoDev, HI_U32 *pu32FrameRate)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_EnableRecvFrameRateMatch (VO_LAYER VoLayer, VO_CHN VoChn)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_DisableRecvFrameRateMatch (VO_LAYER VoLayer, VO_CHN VoChn)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetHdmiParam(VO_DEV VoDev, VO_HDMI_PARAM_S *pstHdmiParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetHdmiParam(VO_DEV VoDev, VO_HDMI_PARAM_S *pstHdmiParam)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_SetVtth(VO_DEV VoDev, HI_U32 u32Vtth)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_GetVtth(VO_DEV VoDev, HI_U32* pu32Vtth)
{
    return HI_SUCCESS;
}

HI_S32 HI_MPI_VO_QueryDevIntfStatus(VO_INTF_TYPE_E enDevInter,VO_DEVINTF_STATUS_S* pstStatus)
{
    return HI_SUCCESS;
}

AHardwareBuffer *TR_VO_Get_VideoLayer_AHardwareBuffer(VO_LAYER VoLayer, RECT_S *pstRect)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];
    //pstLayer->pSurface

    return NULL;
}

int TR_VO_VideoLayer_Get_Buffer(VO_LAYER VoLayer, AHardwareBuffer **buffer)
{
    MPP_VO_VIDEO_LAYER_S *pstLayer;

    pstLayer = &g_stVideoLayers[VoLayer];
    //pstLayer->pSurface

    return TR_SUCCESS;
}

int TR_VO_VideoLayer_Put_Buffer(VO_LAYER VoLayer, AHardwareBuffer *buffer)
{
    return TR_SUCCESS;
}

static void *vo_device_proc_thread(void *arg)
{
    int ret;
    int chnIdx, layerIdx;
    MPP_VO_CHANNEL_S *pstChn;
    MPP_VO_VIDEO_LAYER_S *pstLayer;
    MPP_VO_CONTEXT_S *pCtx = &g_VoCtx;
    PIN_DATA_S *pPins;
    MPP_CHN_S *pBindChn;
    VIDEO_FRAME_INFO_S stVideoFrameSrc;
    VIDEO_FRAME_INFO_S stVideoFrameDst;
    int got_frame;
    VGS_TASK_ATTR_S stTask;
    VIDEO_FRAME_INFO_S stImgIn;
    VIDEO_FRAME_INFO_S stImgOut;
    VGS_HANDLE hVgsHandle;

    LOG_INFO("vo_device_proc_thread start working.\n");

    while (1)
    {
        if (pCtx->quit)
        {
            break;
        }

        for (layerIdx = 0; layerIdx < VO_VIDEO_LAYER_MAX_NUM; layerIdx++)
        {
            pstLayer = &g_stVideoLayers[layerIdx];

            pthread_mutex_lock(&g_VoCtx.stMutex);

            if (!pstLayer->bEnable)
            {
                pthread_mutex_unlock(&g_VoCtx.stMutex);
                continue;
            }

            //1.重新绘制整个layer背景(使用背景色or背景图): layer中chn布局没有变化时不需要重新绘制;
            //2.根据chn Zorder依次绘制chn：priority 越大，优先级越高，越往后绘制。相同priority,从通道号小到大顺序绘制；
            

            pPins = &pstLayer->stPinData;

            //获取Surface的buffer
            AHardwareBuffer *pDestBuffer;
            AHardwareBuffer_Desc destBufferDesc;
            TR_VO_VideoLayer_Get_Buffer(pstLayer->voLayerId, &pDestBuffer);
            AHardwareBuffer_describe(pDestBuffer, &destBufferDesc);

            for (chnIdx = 0; chnIdx < pstLayer->s32MaxChnNum; chnIdx++)
            {
                pstChn = &pstLayer->pstChannels[chnIdx];
                if (!pstChn->bEnable || !pstChn->bVisable)
                {
                    continue;
                }

                if (pPins->pstInPins[chnIdx].bConnect)
                {
                    got_frame = 0;
                    pBindChn = &pPins->pstInPins[chnIdx].stInfo;
                    if (pBindChn->enModId == TR_ID_VPSS)
                    {
                        //timeout == 20ms? 有点长了
                        ret = TR_MPI_VPSS_GetChnFrame(pBindChn->s32DevId, pBindChn->s32ChnId, &stVideoFrameSrc, 20);//20ms
                        if (ret == TR_SUCCESS)
                        {
                            got_frame = 1;
                        }
                        else
                        {
                            LOG_ERR("TR_MPI_VPSS_GetChnFrame failed,ret=0x%x\n", ret);
                        }
                    }
                    
                    if (got_frame)
                    {
                        stVideoFrameDst.stVFrame.u32Width = destBufferDesc.width;
                        stVideoFrameDst.stVFrame.u32Height = destBufferDesc.height;
                        stVideoFrameDst.stVFrame.enPixelFormat = PIXEL_FORMAT_YUV_SEMIPLANAR_420;

                        stVideoFrameDst.stVFrame.pHardwareBuf = (void *)pDestBuffer;

                        stVideoFrameDst.stVFrame.u32Stride[0] = destBufferDesc.stride;
                        stVideoFrameDst.stVFrame.u32Stride[1] = destBufferDesc.stride;

                        stVideoFrameDst.stVFrame.s16OffsetTop = pstChn->stRect.s32Y;
                        stVideoFrameDst.stVFrame.s16OffsetBottom = pstChn->stRect.u32Height;
                        stVideoFrameDst.stVFrame.s16OffsetLeft = pstChn->stRect.s32X;
                        stVideoFrameDst.stVFrame.s16OffsetRight = pstChn->stRect.u32Width;

                        ret = TR_MPI_VGS_BeginJob(&hVgsHandle);
                        if (ret == TR_SUCCESS)
                        {
                            stTask.stImgIn = stVideoFrameSrc;
                            stTask.stImgOut = stVideoFrameDst;
                            ret = TR_MPI_VGS_AddScaleTask(hVgsHandle, &stTask);
                            if (ret == TR_SUCCESS)
                            {
                                ret = TR_MPI_VGS_EndJob(hVgsHandle);
                                if (ret != TR_SUCCESS)
                                {
                                    LOG_ERR("TR_MPI_VGS_EndJob failed,ret=0x%x\n", ret);
                                    TR_MPI_VGS_CancelJob(hVgsHandle);
                                }
                            }
                            else
                            {
                                TR_MPI_VGS_CancelJob(hVgsHandle);
                                LOG_ERR("TR_MPI_VGS_AddScaleTask failed,ret=0x%x\n", ret);
                            }
                        }
                        else
                        {
                            LOG_ERR("TR_MPI_VGS_BeginJob failed,ret=0x%x\n", ret);
                        }
                    }
                }
                else
                {
                    //chn没有绑定源，对应的区域显示为黑色

                }
            }

            TR_VO_VideoLayer_Put_Buffer(pstLayer->voLayerId, pDestBuffer);

            pthread_mutex_unlock(&g_VoCtx.stMutex);
        }

        //wait vsync
        msleep(40);  
    }

    LOG_INFO("vo_device_proc_thread exited.\n");

    pthread_detach(pthread_self());

    return NULL;
}
